package com.chendx.store.seckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chendx.model.common.dtos.ResponseResult;
import com.chendx.model.common.enums.AppHttpCodeEnum;
import com.chendx.model.goods.pojo.Sku;
import com.chendx.model.goods.pojo.Spu;
import com.chendx.model.seckill.dto.SeckillGoodsDto;
import com.chendx.model.seckill.pojo.SeckillGoods;
import com.chendx.model.seckill.vo.SeckillGoodsVo;
import com.chendx.store.common.constants.seckill.SeckillConstants;
import com.chendx.store.common.entity.DateUtil;
import com.chendx.store.seckill.feign.GoodsFeign;
import com.chendx.store.seckill.mapper.SeckillGoodsMapper;
import com.chendx.store.seckill.service.SeckillGoodsService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.*;

/**
 * Created by chendx on 2022/4/22.
 */
@Service
public class SeckillGoodsServiceImpl extends ServiceImpl<SeckillGoodsMapper,SeckillGoods> implements SeckillGoodsService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private GoodsFeign goodsFeign;
    @Autowired
    private TemplateEngine templateEngine;
    @Override
    public ResponseResult load(String time) {
        List<Object> values = redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + time).values();
        if (values == null || values.size() == 0){
            loadSeckillGoods();
            values = redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + time).values();
        }
        List<SeckillGoods> seckillGoodses = JSON.parseArray(values.toString(), SeckillGoods.class);

        return ResponseResult.okResult(seckillGoodses);
    }

    @Override
    public ResponseResult loadSeckillGoods() {
        try {
            List<Date> dateMenus = DateUtil.getDateMenus();
            if (dateMenus != null && dateMenus.size()>0){
                for (Date startTime : dateMenus){
                    LambdaQueryWrapper<SeckillGoods> queryWrapper = new LambdaQueryWrapper<>();
                    String time = DateUtil.date2Str(startTime);
                    queryWrapper.eq(SeckillGoods::getStatus,1);
                    queryWrapper.ge(SeckillGoods::getStartTime,startTime);
                    queryWrapper.lt(SeckillGoods::getEndTime,DateUtil.addDateHour(startTime,2));
                    queryWrapper.gt(SeckillGoods::getStockCount,0);
                    Set<Object> keys = redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + time).keys();
                    if (keys != null && keys.size() > 0){
                        queryWrapper.notIn(SeckillGoods::getId,JSON.parseArray(JSON.toJSONString(keys)));
                    }
                    List<SeckillGoods> seckillGoodses = list(queryWrapper);
                    for (SeckillGoods seckillGoods : seckillGoodses) {
                        SeckillGoodsVo seckillGoodsVo = new SeckillGoodsVo();
                        BeanUtils.copyProperties(seckillGoods,seckillGoodsVo);
                        createPage(time,seckillGoodsVo);
                        redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + time).put(JSON.toJSONString(seckillGoods.getId()), JSON.toJSONString(seckillGoods));
                        String[] pushIds = pushIds(seckillGoods.getStockCount(), String.valueOf(seckillGoods.getId()));
                        redisTemplate.boundListOps(SeckillConstants.SECKILL_GOODS_COUNT_LIST + seckillGoods.getId()).leftPushAll(pushIds);
                        redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_COUNT).increment(JSON.toJSONString(seckillGoods.getId()), seckillGoods.getStockCount());
                    }
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult loadOne(SeckillGoodsDto dto) {
        if (dto == null || dto.getTime() == null || StringUtils.isEmpty(dto.getId())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        Object o = redisTemplate.boundHashOps(SeckillConstants.SECKILL_GOODS_LIST + dto.getTime()).get(dto.getId());
        if (o == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.SECKILL_GOODS_NO_EXIST);
        }
        SeckillGoods seckillGoods = JSON.parseObject(o.toString(), SeckillGoods.class);
        SeckillGoodsVo vo = new SeckillGoodsVo();
        BeanUtils.copyProperties(seckillGoods,vo);
        Sku sku = goodsFeign.findSkuById(seckillGoods.getItemId());
        if (sku == null ){
            return ResponseResult.errorResult(AppHttpCodeEnum.SKU_NOT_EXIST);
        }
        vo.setSku(sku);
        return ResponseResult.okResult(vo);
    }


    private String[] pushIds(Integer stockCount,String id){
        String[] ids = new String[stockCount];
        for (int i = 0; i < ids.length; i++) {
            ids[i] = id;
        }
        return ids;
    }

    private void createPage(String extName,SeckillGoodsVo seckillGoodsVo) {
        Sku sku = goodsFeign.findSkuById(seckillGoodsVo.getItemId());
        seckillGoodsVo.setSku(sku);
        Spu spu = goodsFeign.findById(sku.getSpuId());
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("extName", extName);
        dataMap.put("goods", seckillGoodsVo);
        dataMap.put("sku", sku);
        dataMap.put("spu", spu);
        dataMap.put("imageList", sku.getImages().split(","));
        dataMap.put("specMap", JSON.parseObject(sku.getSpec(), Map.class));


        String path = "F:\\code\\store-protal\\seckillHtml";
        Context context = new Context();
        context.setVariables(dataMap);
        File dir = new File(path);
        if (!dir.mkdirs()) {
            dir.mkdirs();
        }
        File dest = new File(dir, seckillGoodsVo.getId() + ".html");
        try {
            PrintWriter pw = new PrintWriter(dest, "UTF-8");
            templateEngine.process("seckillitem", context, pw);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}
